import { ref } from "vue";
import { loadImage } from ".";
import { globalScale } from "@/config/static";
import {
  Action,
  Direction,
  defaultCharacterConfig,
} from "@/config/characterConfig";
import type {
  CharacterConfig,
  ActionConfig,
  CharacterPartConfig,
} from "@/config/characterConfig";
import { useUserStore } from "@/store/userStore";

// 角色部位的位置偏移量
interface PartOffset {
  x: number;
  y: number;
}

// 角色动画帧配置
interface AnimationFrame {
  body: CharacterPartConfig; // 身体部位的配置
  leftArm?: CharacterPartConfig; // 左手部位的配置
  rightArm?: CharacterPartConfig; // 右手部位的配置
  hair?: CharacterPartConfig; // 发型部位的配置
  hat?: CharacterPartConfig; // 帽子部位的配置
  shirt?: CharacterPartConfig; // 上衣部位的配置
  pants?: CharacterPartConfig; // 裤子部位的配置
}

// 动画状态管理
interface AnimationState {
  frameIndex: number; // 当前帧索引
  frameCounter: number; // 帧计数器
}

// 初始化动画状态
const animationStates = ref<Record<Action, Record<Direction, AnimationState>>>({
  [Action.Run]: {
    [Direction.Down]: { frameIndex: 0, frameCounter: 0 },
    [Direction.Right]: { frameIndex: 0, frameCounter: 0 },
    [Direction.Up]: { frameIndex: 0, frameCounter: 0 },
    [Direction.Left]: { frameIndex: 0, frameCounter: 0 },
  },
});
// 当前方向
const currentDirection = ref<Direction>(Direction.Down);
// 是否在移动
const isMoving = ref<boolean>(false);

// 默认角色配置

/**
 * 渲染角色动画帧
 * @param ctx 画布上下文
 * @param spritesheet 角色精灵图
 * @param action 角色动作
 * @param x 角色在地图上的X坐标
 * @param y 角色在地图上的Y坐标
 * @param scale 缩放比例
 * @param frameCounter 帧计数器
 * @param direction 角色方向
 */
const renderAnimationFrame = (
  ctx: CanvasRenderingContext2D,
  spritesheet: HTMLImageElement,
  action: Action,
  x: number,
  y: number,
  frame: AnimationFrame,
  scale: number,
  frameCounter: number,
  direction: Direction = Direction.Down
) => {
  // 保存当前上下文状态
  ctx.save();

  // 如果是向左方向，应用水平翻转
  if (direction === Direction.Left) {
    // 翻转画布，使用右方向的精灵图
    ctx.scale(-1, 1);
    x = -x - frame.body.config.width * scale; // 调整X坐标以适应翻转
  }

  // 当角色朝右方向时，先渲染身体，再渲染右臂
  // 当角色朝其他方向时，先渲染右臂，再渲染身体
  if (direction === Direction.Right) {
    // 先渲染身体
    ctx.drawImage(
      spritesheet,
      frame.body.config.sourceX + frameCounter * 16,
      frame.body.config.sourceY,
      frame.body.config.width,
      frame.body.config.height,
      x + frame.body.config.offset.x * scale,
      y + frame.body.config.offset.y * scale,
      frame.body.config.width * scale,
      frame.body.config.height * scale
    );

    // 渲染裤子
    if (frame.pants) {
      ctx.drawImage(
        spritesheet,
        frame.pants.config.sourceX,
        frame.pants.config.sourceY,
        frame.pants.config.width,
        frame.pants.config.height,
        x + frame.pants.config.offset.x * scale,
        y + frame.pants.config.offset.y * scale,
        frame.pants.config.width * scale,
        frame.pants.config.height * scale
      );
    }

    // 渲染上衣

    if (frame.shirt) {
      ctx.drawImage(
        spritesheet,
        frame.shirt.config.sourceX,
        frame.shirt.config.sourceY,
        frame.shirt.config.width,
        frame.shirt.config.height,
        x + frame.shirt.config.offset.x * scale,
        y + frame.shirt.config.offset.y * scale,
        frame.shirt.config.width * scale,
        frame.shirt.config.height * scale
      );
    }

    // 渲染左臂
    if (frame.leftArm) {
      ctx.drawImage(
        spritesheet,
        frame.leftArm.config.sourceX + frameCounter * 16,
        frame.leftArm.config.sourceY,
        frame.leftArm.config.width,
        frame.leftArm.config.height,
        x + frame.leftArm.config.offset.x * scale,
        y + frame.leftArm.config.offset.y * scale,
        frame.leftArm.config.width * scale,
        frame.leftArm.config.height * scale
      );
    }

    if (frame.rightArm) {
      ctx.drawImage(
        spritesheet,
        frame.rightArm.config.sourceX + frameCounter * 16,
        frame.rightArm.config.sourceY,
        frame.rightArm.config.width,
        frame.rightArm.config.height,
        x + frame.rightArm.config.offset.x * scale,
        y + frame.rightArm.config.offset.y * scale,
        frame.rightArm.config.width * scale,
        frame.rightArm.config.height * scale
      );
    }
  } else {
    // 其他方向时，先渲染右臂（在身体后面）
    // 渲染左臂
    if (frame.leftArm) {
      ctx.drawImage(
        spritesheet,
        frame.leftArm.config.sourceX + frameCounter * 16,
        frame.leftArm.config.sourceY,
        frame.leftArm.config.width,
        frame.leftArm.config.height,
        x + frame.leftArm.config.offset.x * scale,
        y + frame.leftArm.config.offset.y * scale,
        frame.leftArm.config.width * scale,
        frame.leftArm.config.height * scale
      );
    }

    // 渲染身体
    ctx.drawImage(
      spritesheet,
      frame.body.config.sourceX + frameCounter * 16,
      frame.body.config.sourceY,
      frame.body.config.width,
      frame.body.config.height,
      x + frame.body.config.offset.x * scale,
      y + frame.body.config.offset.y * scale,
      frame.body.config.width * scale,
      frame.body.config.height * scale
    );

    // 渲染裤子
    if (frame.pants) {
      const pantsOffset = isMoving.value ? (frameCounter === 0 ? 0 : 1) : 0;
      ctx.drawImage(
        spritesheet,
        frame.pants.config.sourceX,
        frame.pants.config.sourceY,
        frame.pants.config.width,
        frame.pants.config.height,
        x + frame.pants.config.offset.x * scale,
        y + frame.pants.config.offset.y * scale + pantsOffset,
        frame.pants.config.width * scale,
        frame.pants.config.height * scale
      );
    }

    if (frame.rightArm) {
      ctx.drawImage(
        spritesheet,
        frame.rightArm.config.sourceX + frameCounter * 16,
        frame.rightArm.config.sourceY,
        frame.rightArm.config.width,
        frame.rightArm.config.height,
        x + frame.rightArm.config.offset.x * scale,
        y + frame.rightArm.config.offset.y * scale,
        frame.rightArm.config.width * scale,
        frame.rightArm.config.height * scale
      );
    }

    // 渲染上衣
    if (frame.shirt) {
      const shirtOffset = isMoving.value ? (frameCounter === 0 ? 0 : 1) : 0;
      ctx.drawImage(
        spritesheet,
        frame.shirt.config.sourceX,
        frame.shirt.config.sourceY,
        frame.shirt.config.width,
        frame.shirt.config.height,
        x + frame.shirt.config.offset.x * scale,
        y + frame.shirt.config.offset.y * scale + shirtOffset,
        frame.shirt.config.displayWidth * scale,
        frame.shirt.config.displayHeight * scale
      );
    }
  }

  // 渲染发型
  if (frame.hair && !frame.hat) {
    const hariBobOffset = isMoving.value ? (frameCounter === 0 ? 0 : 1) : 0;
    ctx.drawImage(
      spritesheet,
      frame.hair.config.sourceX,
      frame.hair.config.sourceY,
      frame.hair.config.width,
      frame.hair.config.height,
      x + frame.hair.config.offset.x * scale,
      y + frame.hair.config.offset.y * scale + hariBobOffset,
      frame.hair.config.width * scale,
      frame.hair.config.height * scale
    );
  }

  // 渲染帽子
  if (frame.hat) {
    const hatBobOffset = isMoving.value ? (frameCounter === 0 ? 0 : 1) : 0;
    ctx.drawImage(
      spritesheet,
      frame.hat.config.sourceX,
      frame.hat.config.sourceY,
      frame.hat.config.width,
      frame.hat.config.height,
      x + frame.hat.config.offset.x * scale,
      y + frame.hat.config.offset.y * scale + hatBobOffset,
      frame.hat.config.width * scale,
      frame.hat.config.height * scale
    );
  }
  ctx.restore();
};

/**
 * 渲染角色
 * @param ctx 画布上下文
 * @param spritesheet 角色精灵图
 * @param y 角色在地图上的Y坐标
 * @param x 角色在地图上的X坐标
 * @param action 角色动作
 * @param frameIndex 角色帧索引
 * @param scale 缩放比例
 * @param direction 角色方向
 */
export const renderCharacter = (
  ctx: CanvasRenderingContext2D,
  spritesheet: HTMLImageElement,
  y: number,
  x: number,
  action: Action = Action.Run,
  frame: AnimationFrame,
  scale: number = globalScale,
  frameCounter: number,
  direction: Direction = Direction.Down
) => {
  ctx.save();
  ctx.imageSmoothingEnabled = false;
  renderAnimationFrame(
    ctx,
    spritesheet,
    action,
    x,
    y,
    frame,
    scale,
    frameCounter,
    direction
  );
  ctx.restore();
};

/**
 * 角色动画控制器
 */
export class CharacterAnimationController {
  private spritesheet: HTMLImageElement; // 角色精灵图
  private action: Action = Action.Run; // 当前动作
  private direction: Direction = 1; // 当前方向
  private dateFrameIndex: number = 0; // 当前帧索引
  private lastFrameTime: number = 0; // 上一帧时间
  private config: CharacterConfig; // 角色配置
  private ctx: CanvasRenderingContext2D; // 画布上下文
  private elapsedTime: number = 0; // 动画时间
  private frameChangeInterval: number = 0.1; // 帧切换间隔

  // 添加服装配置属性
  private hatConfig?: CharacterPartConfig; // 帽子配置
  private hairConfig?: CharacterPartConfig; // 发型配置
  private shirtConfig?: CharacterPartConfig; // 上衣配置
  private pantsConfig?: CharacterPartConfig; // 裤子配置

  constructor(
    spritesheet: HTMLImageElement,
    ctx: CanvasRenderingContext2D,
    config: CharacterConfig = defaultCharacterConfig
  ) {
    this.spritesheet = spritesheet;
    this.config = config;
    this.ctx = ctx;

    // 初始化服装配置
    const defaultFrame =
      defaultCharacterConfig.actions[this.action][this.direction].frames[0];
    this.hatConfig = defaultFrame.hat;
    this.pantsConfig = defaultFrame.pants;
    this.shirtConfig = defaultFrame.shirt;
  }

  /**
   * 设置帽子
   * @param hatConfig 帽子配置，传入null则移除帽子
   */
  setHat(hatConfig: CharacterPartConfig | null) {
    this.hatConfig = hatConfig || undefined;
  }

  /**
   * 设置发型
   */
  setHair(hairConfig: CharacterPartConfig | null) {
    this.hairConfig = hairConfig || undefined;
  }

  /**
   * 设置上衣
   */
  setShirt(shirtConfig: CharacterPartConfig | null) {
    this.shirtConfig = shirtConfig || undefined;
  }

  /**
   * 设置裤子
   */
  setPants(pantsConfig: CharacterPartConfig | null) {
    this.pantsConfig = pantsConfig || undefined;
  }

  /**
   * 设置帽子
   */
  setHatConfig(hatConfig: CharacterPartConfig | null) {
    this.hatConfig = hatConfig || undefined;
  }

  /**
   * 设置角色动作
   * @param action 角色动作
   * @param direction 角色方向
   * @param isMoving 是否正在移动
   */
  setAction(action: Action, direction: Direction, moving: boolean = false) {
    isMoving.value = moving;
    // 当角色的动作或方向发生变化时，才重置动画状态
    if (this.action !== action || this.direction !== direction) {
      this.action = action;
      this.dateFrameIndex = 0;
      this.direction = direction;
      this.lastFrameTime = performance.now();
    }
  }

  /**
   * 更新动画
   */
  update(x: number, y: number, scale: number = globalScale, timestamp: number) {
    const actionConfig = this.config.actions[this.action][this.direction];
    const state = animationStates.value[this.action][this.direction]; // 获取当前动作和方向的动画状态
    const frameDuration = 1000 / actionConfig.framesCount; // 每帧持续时间（毫秒

    // 计算deltaTime（当前时间戳与上一帧时间戳的差值）
    const deltaTime = Math.min(timestamp - this.lastFrameTime, frameDuration);

    if (isMoving.value) {
      // 如果时间超过了一帧的持续时间，则切换到下一帧
      if (deltaTime >= frameDuration) {
        this.dateFrameIndex =
          (this.dateFrameIndex + 1) % actionConfig.frames.length;
        this.lastFrameTime = timestamp; // 更新上一帧时间
      }

      this.elapsedTime += timestamp;

      // 计算当前帧的索引
      if (this.elapsedTime > this.frameChangeInterval) {
        state.frameCounter =
          (state.frameCounter + 1) % actionConfig.spriteFramesCount;
        this.elapsedTime -= this.frameChangeInterval;
      }
    } else {
      this.dateFrameIndex = 0;
      state.frameCounter = 0;
    }

    const baseFrame = actionConfig.frames[this.dateFrameIndex];
    const characterWidth = baseFrame.body.config.width * scale;
    const characterHeight = baseFrame.body.config.height * scale;

    const userStore = useUserStore();
    userStore.setCharacterSize(characterWidth, characterHeight);

    this.render(this.ctx, x, y, scale, actionConfig, state.frameCounter);
  }

  /**
   * 渲染角色
   * @param ctx 画布上下文
   * @param x 角色在地图上的X坐标
   * @param y 角色在地图上的Y坐标
   * @param scale 缩放比例
   * @param actionConfig 角色动作配置
   * @param frameCounter 角色帧索引
   */
  render(
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    scale: number = globalScale,
    actionConfig: ActionConfig,
    frameCounter: number
  ) {
    const baseFrame = actionConfig.frames[this.dateFrameIndex]; // 获取当前帧的配置
    // 创建包含自定义服装的完整动作配置
    const completeFrame: AnimationFrame = {
      ...baseFrame,
      hat: baseFrame.hat || this.hatConfig,
      hair: baseFrame.hair || this.hairConfig,
      shirt: baseFrame.shirt || this.shirtConfig,
      pants: baseFrame.pants || this.pantsConfig,
    };

    renderCharacter(
      ctx,
      this.spritesheet,
      y,
      x,
      this.action,
      completeFrame,
      scale,
      frameCounter,
      this.direction
    );
  }
}

/**
 * 创建角色动画控制器
 * @param spritesheetPath 角色精灵图路径
 * @param ctx 画布上下文
 */
export const createCharacterAnimationController = async (
  spritesheetPath: string,
  ctx: CanvasRenderingContext2D
): Promise<CharacterAnimationController> => {
  const spritesheet = await loadImage(spritesheetPath);
  return new CharacterAnimationController(spritesheet, ctx);
};
